/**
 * @copyright Copyright (c) 2024 COOREAL. All rights reserved.
 * @description AbstractScene.ts
 * @author xuezejun @date 2025/07/02
 */

import * as BABYLON from "@babylonjs/core";
import * as GUI from "@babylonjs/gui";
import { BabylonCanvas } from "./BabylonCanvas";xor
import { TWcsScene } from "../models/TWcsScene";
import { ClassHelper } from "../ClassHelper";
import { TWcsSceneCamera } from "../models/TWcsSceneCamera";
import { BabylonDevice2d } from "./2d/BabylonDevice2d";
import { xor } from "lodash";
import { BabylonDevice3d } from "./3d/BabylonDevice3d";
/**
 * 提供一个抽象场景类，定义出场景的基本操作和属性事件。
 * 操作说明：
 * 1. 鼠标右键用于拖动（平移）场景。
 * 2. 鼠标左键：
 *    左键按下的时候如果下面是设备则选中设备，如果下面的设备已存在与已选中设备组则无操作，开启拖动。
 *    左键按下的时候如果下面不是设备，则拉出选择框，选择设备。
 *    左键按下后如果已经有选中设备，则移动的时候拖动选中设备。
 *    左键抬起的时候如果是拖动则释放拖动，如果是选择框则设置设备选中。
 * 3. 鼠标中键
 *    滚动的时候缩放。
 *    按下拖动用于3D场景时旋转场景。
 */
export class BabylonScene extends BABYLON.Scene {
  public id: string;
  public data: TWcsScene;
  public device2ds: BabylonDevice2d[] = [];
  public device3ds: BabylonDevice3d[] = [];
  public canvas: BabylonCanvas;
  public scene: BABYLON.Scene;
  public cameras: BABYLON.Camera[] = [];
  public lights: BABYLON.Light[] = [];
  public ui: GUI.AdvancedDynamicTexture;
  public active: boolean;
  /** 获取或设置设计模式：允许框选、拖动位置、调整大小 */
  public isDesignMode: boolean = false;
  public backgroudColor: string;
  //public activeCamera: BABYLON.Camera | undefined;
  protected assetsManager: BABYLON.AssetsManager;

  constructor(canvas: BabylonCanvas, tWcsScene: TWcsScene) {
    super(canvas.engine);
    this.id = tWcsScene.sceneId || "default-scene";
    this.canvas = canvas;
    this.data = tWcsScene;
    this.scene = new BABYLON.Scene(canvas.engine);
    this.assetsManager = new BABYLON.AssetsManager(this.scene);
    this.ui = GUI.AdvancedDynamicTexture.CreateFullscreenUI(
      `${this.id}-ui`,
      true,
      this.scene
    );
    this.backgroudColor = this.data.clearColor ?? "transparent";
    this.scene.clearColor = BABYLON.Color4.FromHexString(this.backgroudColor);
    this.active = this.data.isActived || false;
  }

  public async init() {
    // 没有定义相机数据的则创建一个默认相机数据。
    if (this.data.tWcsSceneCameras.length == 0) {
      var defaultCamera = new BABYLON.Camera(this.id + "-camera-defaut", new BABYLON.Vector3(0, 0, 0), this.scene);
      this.cameras.push(defaultCamera);
    }

    // 创建相机
    for (var tWcsLayoutCamera of this.data.tWcsSceneCameras) {
      var cls = tWcsLayoutCamera.cameraClassType;
      var cameraId = tWcsLayoutCamera.cameraId;
      var alpha = tWcsLayoutCamera.alpha;
      var beta = tWcsLayoutCamera.beta;
      var radius = tWcsLayoutCamera.radius;
      var target = new BABYLON.Vector3(
        tWcsLayoutCamera.targetX,
        tWcsLayoutCamera.targetY,
        tWcsLayoutCamera.targetZ
      );
      var camera = ClassHelper.createInstance<BABYLON.Camera>(
        cls,
        cameraId,
        alpha,
        beta,
        radius,
        target,
        this.scene
      );
      if (!camera) {
        throw `Camera[${cls}] create error.`;
      }

      camera.attachControl(this.canvas.canvasElement, true);
      this.cameras.push(camera);
    }

    // 创建灯光
    for (var tWcsLayoutLight of this.data.tWcsSceneLights) {
      var cls = tWcsLayoutLight.lightClassType!;
      var lightId = tWcsLayoutLight.lightId;
      var direction = new BABYLON.Vector3(
        tWcsLayoutLight.targetX,
        tWcsLayoutLight.targetY,
        tWcsLayoutLight.targetZ
      );
      var light = ClassHelper.createInstance<BABYLON.Light>(
        cls,
        lightId,
        direction,
        this.scene
      );
      if (!light) {
        throw `Light[${cls}] create error.`;
      }

      light.intensity = 0.5;
      this.lights.push(light);
    }

    // 按数据定义创建设备。
    for (var tWcsSceneDevice2d of this.data.tWcsSceneDevice2ds) {
      var device2d = new BabylonDevice2d(this, tWcsSceneDevice2d);
      device2d.init();
      this.device2ds.push(device2d);
    }
  }
}
